﻿using System;
using System.Web.Mvc;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;
using WebSite.ViewModels;
using WebSite.ViewModels.DetailsViewModels;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace ControleRepresentante.UnitTests.Controllers
{
    [TestClass]
    public class VendedorControllerTests : CRUDControllerTestScenarioBase<VendedorController, Vendedor, IVendedorRepository, StatisticsBase>
    {
        const string Nome = "a";
        const string CPF = "1234";
        const string Identidade = "4321";
        private readonly DateTime m_Nascimento = DateTime.Now;
        private Representante m_Representante;

        protected override VendedorController CreateController(bool isRepresentante = true)
        {
            this.LoginAsAdmin();
            Guid representanteId = this.CreateRepresentante("repre", true, "repreuser");
            Guid otherRepresentanteId = this.CreateRepresentante("otherrepre", false, "other");
            IRepresentanteRepository representanteRepository = RepositoryProvider.GetRepository<IRepresentanteRepository>();
            m_Representante = representanteRepository.GetModelById(representanteId);
            Representante otherRepresentante = representanteRepository.GetModelById(otherRepresentanteId);
            new Vendedor {Nome = "a"}.Representante = otherRepresentante;
            new Vendedor {Nome = "b"}.Representante = otherRepresentante;
            if (isRepresentante)
            {
                this.Logout();
                this.LoginAs("repreuser");
            }
            return new VendedorController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider, ImpostProvider);
        }

        protected override Vendedor CreateModel()
        {
            return new Vendedor {Nome = Guid.NewGuid().ToString(), Representante = m_Representante};
        }

        protected override ActionResult Create(VendedorController controller)
        {
            return controller.Create(Nome, m_Nascimento, CPF, Identidade);
        }

        protected override void VerifyModel(Vendedor model)
        {
            Assert.AreEqual(Nome, model.Nome);
            Assert.AreEqual(m_Nascimento, model.Nascimento);
            Assert.AreEqual(CPF, model.CPF);
            Assert.AreEqual(Identidade, model.Identidade);
        }

        protected override ActionResult CreateEmptyFields(VendedorController controller)
        {
            return controller.Create(String.Empty, m_Nascimento, CPF, Identidade);
        }

        protected override void VerifyModelEmptyFields(Vendedor model)
        {
            Assert.AreEqual(String.Empty, model.Nome);
            Assert.AreEqual(m_Nascimento, model.Nascimento);
            Assert.AreEqual(CPF, model.CPF);
            Assert.AreEqual(Identidade, model.Identidade);
        }

        protected override ActionResult CreateDuplicatedModel(VendedorController controller, Vendedor model)
        {
            return controller.Create(model.Nome, m_Nascimento, CPF, Identidade);
        }

        protected override void VerifyDuplicatedModel(Vendedor originalModel, Vendedor duplicatedModel)
        {
            Assert.AreEqual(originalModel.Nome, duplicatedModel.Nome);
            Assert.AreEqual(m_Nascimento, duplicatedModel.Nascimento);
            Assert.AreEqual(CPF, duplicatedModel.CPF);
            Assert.AreEqual(Identidade, duplicatedModel.Identidade);
        }

        protected override ActionResult Edit(VendedorController controller)
        {
            return controller.Edit(Nome, m_Nascimento, CPF, Identidade);
        }

        protected override ActionResult EditEmptyFields(VendedorController controller)
        {
            return controller.Edit(String.Empty, m_Nascimento, CPF, Identidade);
        }

        protected override ActionResult EditDuplicatedModel(VendedorController controller, Vendedor modelToDuplicate)
        {
            return controller.Edit(modelToDuplicate.Nome, m_Nascimento, CPF, Identidade);
        }

        [TestMethod]
        [ExpectedException(typeof(LoginException))]
        public void TestVendedoresNotAtivoRepresentante()
        {
            VendedorController vendedorController = CreateController(false);
            this.LoginAs("other");
            vendedorController.Index();
        }

        [TestMethod]
        public void TestUnableToDeleteVendedorWithCliente()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();

            this.LoginAs("user");
            Guid vendedorId = this.CreateVendedor(new Vendedor{Nome = "vendedor"});
            Cliente cliente = new Cliente
            {
                RazaoSocial = "razao social",
                NomeFantasia = "nome fantasia",
                Vendedor = new Vendedor {Id = vendedorId}
            };
            this.CreateCliente(cliente);

            using (VendedorController vendedorController = new VendedorController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider, ImpostProvider))
            {
                ActionResult actionResult = vendedorController.Delete(vendedorId);
                Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
                ViewResult viewResult = (ViewResult) actionResult;
                Assert.IsInstanceOfType(viewResult.Model, typeof(CRUDViewModel));
                CRUDViewModel crudViewModel = (CRUDViewModel) viewResult.Model;
                Assert.IsNotNull(crudViewModel.Message);
            }
        }

        [TestMethod]
        public void TestCreateAndDeleteFullVendedor()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();

            this.LoginAs("user");
            this.CreateAttribute(AttributeType.Vendedor, "my attribute");
            Vendedor vendedor = new Vendedor
            {
                CPF = "cpf",
                Identidade = "identidade",
                Nascimento = DateTime.Now,
                Nome = "nome"
            };
            vendedor.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "my attribute value"
            });
            vendedor.AddContato(new Contato
            {
                Tipo = ContatoType.FaxResidencial,
                Valor = "my contato valor",
                Observacao = "my contato observacao",
                Principal = true
            });
            vendedor.AddConta(new Conta
            {
                Agencia = "agencia",
                Banco = "banco",
                Numero = "numero",
                Observacao = "observacao",
                Principal = true
            });
            vendedor.AddEndereco(new Endereco
            {
                Bairro = "bairro",
                CEP = "cep",
                Cidade = "cidade",
                Complemento = "complemento",
                Estado = "estado",
                Numero = "numero",
                Observacao = "observacao",
                Rua = "rua",
                Tipo = EnderecoType.Residencial,
                Principal = true
            });
            Guid vendedorId = this.CreateVendedor(vendedor);
            this.DeleteVendedor(vendedorId);
        }

        [TestMethod]
        public void TestUnableToDeleteVendedorWithPedido()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("repre", true, "u");
            this.Logout();
            this.LoginAs("u");
            Guid vendedorId = this.CreateVendedor("vendedor");
            Guid vendedor2Id = this.CreateVendedor("vendedor2");
            Guid clienteId = this.CreateCliente("nome", vendedor2Id);
            Guid transportadoraId = this.CreateTransportadora("transportadora");
            Guid fabricaId = this.CreateFabrica("fabrica");
            this.CreatePedido(vendedorId, clienteId, transportadoraId, fabricaId);
            using (VendedorController vendedorController = new VendedorController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider, ImpostProvider))
            {
                ActionResult actionResult = vendedorController.Delete(vendedorId);
                Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
                ViewResult viewResult = (ViewResult) actionResult;
                Assert.IsInstanceOfType(viewResult.Model, typeof(VendedorDetailsViewModel));
                VendedorDetailsViewModel vendedorDetailsViewModel = (VendedorDetailsViewModel) viewResult.Model;
                Assert.IsNotNull(vendedorDetailsViewModel.Message);
            }
        }
    }
}
